/*
 * @features: 主要功能
 * @description: 内容说明
 * @Date: 2021-09-29 14:48:45
 * @Author: judu233(769471424@qq.com)
 * @LastEditTime: 2021-10-07 20:51:52
 * @LastEditors: judu233
 */

import c3d from "../../../cc";
declare module "cc" {
    export namespace math {
        /**范围检查 */
        export let check: RangeChack;
    }
}
export default class RangeChack {
    /**
    * 判断numberStr是否在interval区间范围内
    * @param numberStr 数值类型的字符串
    * @param interval 正常的数学区间，包括无穷大等，如：(0, 100]、<50、(-∞,8]、(10%,50%)U(80%,100%)
    * @return true：表示numberStr在区间interval范围内，false：表示numberStr不在区间interval范围内
    * @example
    *   isInTheInterval('5','[0,10]')=> true
    */
    isInTheInterval(numberStr: string, interval: string) {
        // 将区间和numberStr转化为可计算的表达式
        let formula = this.getFormulaByAllInterval(numberStr, interval, "||");
        try {
            let reult = eval(formula);
            c3d.Out.log(`表达式：${formula}, 结果:${reult}`);
            return reult;
        } catch (e) {
            c3d.Out.log("计算表达式为：" + formula);
        }
    }

    /**
     * 将所有阀值区间转化为公式：如
     * <pre>
     * [60,100] 转为 numberStr >= 60 && numberStr <= 100
     * (18%,56%)U(86%,100%) 转为 (numberStr > 0.18 && numberStr < 0.56) || (numberStr > 0.86 && numberStr < 1)
     * </pre>
     *
     * @param numberStr 数值类型的字符串
     * @param interval 数学区间
     * @param connector 连接符
     */
    getFormulaByAllInterval(numberStr: string, interval: string, connector: string) {
        let sb = '';
        let inter = interval.split("U");
        for (let halfInterval of inter) {
            let formula = this.getFormulaByInterval(numberStr, halfInterval, " && ");
            sb += `(${formula}) ${connector}`;
        }
        let allLimitInvel = sb.toString();
        let index = allLimitInvel.lastIndexOf(connector);
        allLimitInvel = allLimitInvel.substring(0, index);
        return allLimitInvel;
    }

    /**
     * 将整个阀值区间转化为公式：如
     * @param numberStr 数值类型的字符串
     * @param interval 数学区间
     * @param connector 连接符
     * @example
     *  <pre>
     *  [60, 100] 转为 numberStr >= 60 && numberStr <= 100
     *  </pre>
     */
    private getFormulaByInterval(numberStr: string, interval: string, connector: string) {
        let sb = '';
        // 如：[60, 100]
        let inter = interval.split(",");
        for (let halfInterval of inter) {
            // 将半个阀值区间转化为公式
            let formula = this.getFormulaByHalfInterval(halfInterval, numberStr);
            sb += formula + connector;
        }
        let limitInvel = sb.toString();
        let index = limitInvel.lastIndexOf(connector);
        limitInvel = limitInvel.substring(0, index);
        return limitInvel;
    }

    /**
     * 将半个阀值区间转化为公式：如
     * @param halfInterval 半个阀值区间，如：60)
     * @param numberStr 数值类型的字符串
     * @example
     *  <pre>
     *  60) 转为 numberStr < 60
     *  ≥88% 转为 numberStr >= 0.88
     *  [60 转为 numberStr >= 60
     *  <50% 转为 numberStr < 0.5
     *  </pre>
     */
    private getFormulaByHalfInterval(halfInterval: string, numberStr: string) {
        halfInterval = halfInterval.trim();
        // 包含无穷大则不需要公式
        if (halfInterval.includes("∞")) {
            return "1 == 1";
        }
        let formula = '';
        let number = "";
        let opera = "";
        // 表示判断方向（如>）在前面 如：≥88%
        let regex = "^([<>≤≥\\[\\(]{1}(-?\\d+.?\\d*\\%?))$";
        if (halfInterval.match(regex)) {
            opera = halfInterval.substring(0, 1);
            number = halfInterval.substring(1);
        } else {
            opera = halfInterval.substring(halfInterval.length - 1);
            number = halfInterval.substring(0, halfInterval.length - 1);
        }
        let value = this.dealPercent(number);
        formula = `${numberStr} ${opera} ${value}`;
        let res = formula.toString();
        // 转化特定字符
        res = res.replace("[", ">=");
        res = res.replace("(", ">");
        res = res.replace("]", "<=");
        res = res.replace(")", "<");
        res = res.replace("≤", "<=");
        res = res.replace("≥", ">=");
        return res;
    }

    /**
     * 去除百分号，转为小数
     * @param str 可能含百分号的数字
     * @return
     */
    private dealPercent(str: string) {
        let bigDecimal = 0;
        if (str.includes("%")) {
            str = str.substring(0, str.length - 1);
            bigDecimal = Number(str) / 100;
        } else {
            bigDecimal = Number(str);
        }
        return bigDecimal;
    }
}
